/*
 * Copyright 2006 Brian Watkins
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */


package bw.weather;

import org.xml.sax.*;
import org.xml.sax.helpers.*;

public class WeatherXmlHandler extends DefaultHandler
{
    private static String LOCATION_TAG = "loc";
    private static String LOCATION_NAME_TAG = "dnam";
    private static String CURRENT_CONDITIONS_TAG = "cc";
    private static String CURRENT_TEMP_TAG = "tmp";
    private static String CURRENT_FLK_TAG = "flik";
    private static String WEATHER_DESC_TAG = "t";
    private static String FORECAST_TAG = "day";
    private static String FORECAST_DAY_ATTR = "t";
    private static String FORECAST_ID_ATTR = "d";
    private static String FORECAST_HI_TAG = "hi";
    private static String FORECAST_LOW_TAG = "low";
    private static String FORECAST_PART_TAG = "part";
    private static String FORECAST_PART_NAME_ATTR = "p";
    private static String WIND_TAG = "wind";
    private static String UV_TAG = "uv";
    private static String MOON_TAG = "moon";
    private static String ERROR_TAG = "error";

    private static String FORECAST_PART_DAY = "d";
    private static String FORECAST_PART_NIGHT = "n";

    private WeatherReport _report = null;
    private DailyForecastInfo _currentForecast = null;
    private StringBuffer _characters = new StringBuffer();

    private boolean _inForecast = false;
    private boolean _inForecastDay = false;
    private boolean _inForecastNight = false;
    private boolean _ignoreDescTag = false;
    private boolean _inError = false;

    public WeatherXmlHandler ()
    {
        _report = new WeatherReport();
    }
    
    public WeatherReport getReport ()
    {
        return _report;
    }

    public void startElement ( String uri, String localName,
                               String qName, Attributes attributes )
    {
        if ( qName.equalsIgnoreCase( LOCATION_NAME_TAG ) ||
             qName.equalsIgnoreCase( CURRENT_TEMP_TAG ) ||
             qName.equalsIgnoreCase( CURRENT_FLK_TAG ) ||
             qName.equalsIgnoreCase( WEATHER_DESC_TAG ) ||
             qName.equalsIgnoreCase( FORECAST_HI_TAG ) ||
             qName.equalsIgnoreCase( FORECAST_LOW_TAG ) )
        {
            clearCharacters();
        }
        else if ( qName.equalsIgnoreCase( FORECAST_TAG ) )
        {
            int forecastId = Integer.parseInt( attributes.getValue( FORECAST_ID_ATTR ) );
            _currentForecast = new DailyForecastInfo( forecastId );
            _currentForecast.setDayName( attributes.getValue( FORECAST_DAY_ATTR ) );
            _inForecast = true;
        }
        else if ( _inForecast && qName.equalsIgnoreCase( FORECAST_PART_TAG ) )
        {
            String partName = attributes.getValue( FORECAST_PART_NAME_ATTR );
            if ( partName.equalsIgnoreCase( FORECAST_PART_DAY ) )
            {
                _inForecastDay = true;
            }
            else if ( partName.equalsIgnoreCase( FORECAST_PART_NIGHT ) )
            {
                _inForecastNight = true;
            }
        }
        else if ( qName.equalsIgnoreCase( WIND_TAG ) ||
                  qName.equalsIgnoreCase( UV_TAG ) ||
		  qName.equalsIgnoreCase( MOON_TAG ) )
        {
            _ignoreDescTag = true;
        }
        else if ( qName.equalsIgnoreCase( ERROR_TAG ) )
        {
            _inError = true;
        }
    }

    public void endElement ( String uri, String localName, String qName )
    {
        if ( qName.equalsIgnoreCase( LOCATION_NAME_TAG ) )
        {
            _report.setLocation( getCharacters() );
        }
        else if ( qName.equalsIgnoreCase( CURRENT_TEMP_TAG ) )
        {
            _report.setTemp( getCharacters() );
        }
        else if ( qName.equalsIgnoreCase( CURRENT_FLK_TAG ) )
        {
            _report.setFeelsLikeTemp( getCharacters() );
        }
        else if ( !_ignoreDescTag && qName.equalsIgnoreCase( WEATHER_DESC_TAG ) )
        {
            if ( !_inForecast )
            {
                _report.setWeatherDesc( getCharacters() );
            }
            else if ( _inForecast && _inForecastDay ) 
            {
                _currentForecast.setDayWeatherDesc( getCharacters() );
            }
            else if ( _inForecast && _inForecastNight )
            {
                _currentForecast.setNightWeatherDesc( getCharacters() );
            }
        }
        else if ( qName.equalsIgnoreCase( FORECAST_TAG ) )
        {
            if ( _currentForecast != null )
            {
                _report.addDailyForecast( _currentForecast );
                _currentForecast = null;
            }
            _inForecast = false;
        }
        else if ( qName.equalsIgnoreCase( FORECAST_HI_TAG ) && 
                  _currentForecast != null )
        {
            _currentForecast.setHiTemp( getCharacters() );
        }
        else if ( qName.equalsIgnoreCase( FORECAST_LOW_TAG ) && 
                  _currentForecast != null )
        {
            _currentForecast.setLowTemp( getCharacters() );
        }
        else if ( qName.equalsIgnoreCase( FORECAST_PART_TAG ) )
        {
            _inForecastDay = false;
            _inForecastNight = false;
        }
        else if ( qName.equalsIgnoreCase( WIND_TAG ) ||
                  qName.equalsIgnoreCase( UV_TAG ) ||
		  qName.equalsIgnoreCase( MOON_TAG ) )
        {
            _ignoreDescTag = false;
        }
        else if ( qName.equalsIgnoreCase( ERROR_TAG ) )
        {
            _report.setError( getCharacters() );
            _inError = false;
        }
    }

    public void characters ( char [] ch, int start, int length )
    {
        _characters.append( ch, start, length );
    }

    private String getCharacters()
    {
        return _characters.toString();
    }

    private void clearCharacters ()
    {
        _characters = new StringBuffer();
    }
}